/*
 * Copyright (C) 2011 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.hunantv.mglive.widget.animation;

import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.ColorMatrix;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.media.Image;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.View;

import com.hunantv.mglive.R;

import java.util.ArrayList;
import java.util.Random;

/**
 * This class is the custom view where all of the Droidflakes are drawn. This
 * class has all of the logic for adding, subtracting, and rendering
 * Droidflakes.
 */
public class FlakeView extends View {

    private static final int BITMAP_NUM = 5;
    public static final int MAX_LEVEL_NUM = 5;
    public static final int MIN_LEVEL_NUM = 1;
    public static final int LEVEL_NUM_1 = 1;
    public static final int LEVEL_NUM_2 = 2;
    public static final int LEVEL_NUM_3 = 3;
    public static final int LEVEL_NUM_4 = 4;
    public static final int LEVEL_NUM_5 = 5;
    private int level = MIN_LEVEL_NUM;

    private static final int LEVEL_BITMAP_NUM = 6;
    Bitmap[] droids = new Bitmap[BITMAP_NUM]; // The bitmap that all flakes use
    ArrayList<Flake> flakes = new ArrayList<Flake>(); // List of current flakes
    //存储点击效果的礼物动画
    ArrayList<Flake> flakesClick = new ArrayList<Flake>();

    // Animator used to drive all separate flake animations. Rather than have
    // potentially
    // hundreds of separate animators, we just use one and then update all
    // flakes for each
    // frame of that single animation.
    ValueAnimator animator = ValueAnimator.ofFloat(0, 1);
    long startTime, prevTime; // Used to track elapsed time for animations and
    // fps
    Matrix m = new Matrix(); // Matrix used to translate/rotate each flake

    /**
     * 动画起始点Y
     */
    private int mStartX;
    /**
     * 动画起始点
     */
    private int mStartY;

    public void setStartPosition(int x, int y) {
        mStartX = x;
        mStartY = y;
    }

    private static final int MSG_X = 1;
    private static final int MSG_Y = 2;

    private Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            if (msg.what == MSG_X) {//横向速度变化
                for (int i = 0; i < flakes.size(); ++i) {
                    Flake flake = flakes.get(i);
                    changeXSpeed(flake);

                }
                for (int i = 0; i < flakesClick.size(); ++i) {
                    Flake flake = flakesClick.get(i);
                    changeXSpeed(flake);
                }

                Message msgY = new Message();
                msgY.what = MSG_Y;
                sendMessageDelayed(msgY, 500);

            } else if (msg.what == MSG_Y) {//纵向速度变化
                for (int i = 0; i < flakes.size(); ++i) {
                    Flake flake = flakes.get(i);
                    changeYSpeed(flake);
                }

                for (int i = 0; i < flakesClick.size(); ++i) {
                    Flake flake = flakesClick.get(i);
                    changeYSpeed(flake);
                }

                Message msgX = new Message();
                msgX.what = MSG_X;
                sendMessageDelayed(msgX, 500);
            }

        }

        private void changeXSpeed(Flake flake){
            double sX = Math.random() - 0.5;
            if (sX >= 0) {
                flake.speedX = (float) (Math.min(0.2, sX)) * 150;
            } else {
                flake.speedX = (float) (Math.min(-0.2, sX)) * 150;
            }
        }

        private void changeYSpeed(Flake flake){
            flake.speedY = -200 - (float) Math.random() * 50;
        }

    };
    private static final int MSG_LIST = 3;
    private Handler mListHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            int index = msg.arg1;
            if (index < flakes.size()) {
                flakes.get(index).isRealeyToShow = true;
                Message msgL = new Message();
                msgL.what = MSG_LIST;
                msgL.arg1 = index + 1;
                sendMessageDelayed(msgL, 800 - 50 * level);
            }
        }
    };

    private void initBitmaps() {
        droids[0] = BitmapFactory.decodeResource(getResources(), R.drawable.anim_xin);
        droids[1] = BitmapFactory.decodeResource(getResources(), R.drawable.anim_star);
        droids[2] = BitmapFactory.decodeResource(getResources(), R.drawable.anim_ren);
        droids[3] = BitmapFactory.decodeResource(getResources(), R.drawable.anim_praise);
        droids[4] = BitmapFactory.decodeResource(getResources(), R.drawable.anim_lei);
    }

    /**
     * Constructor. Create objects used throughout the life of the View: the
     * Paint and the animator
     */
    public FlakeView(Context context) {
        super(context);
        initBitmaps();

        // This listener is where the action is for the flak animations. Every
        // frame of the
        // animation, we calculate the elapsed time and update every flake's
        // position and rotation
        // according to its speed.
        animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator arg0) {
                long nowTime = System.currentTimeMillis();
                float secs = (float) (nowTime - prevTime) / 1000f;
                prevTime = nowTime;

                //正常状态下的动画
                for (int i = 0; i < flakes.size(); ++i) {
                    Flake flake = flakes.get(i);
                    if (flake.isRealeyToShow) {
                        //大小
                        flake.scale = flake.scale + 0.1f;
                        if (flake.scale > 1) {
                            flake.scale = 1;
                        }

                        if (flake.scale == 1) {
                            //位置
                            flake.y += (flake.speedY * secs);
                            flake.x += (flake.speedX * secs);

                            //飘动一段时间后改变透明度
                            if (flake.y < -getHeight() / 7) {
                                int cut = flake.alpha/20;
                                if(cut<1){
                                    cut = 1;
                                }
                                flake.alpha = flake.alpha - cut;
                                if (flake.alpha < 0) {
                                    flake.alpha = 0;
                                }
                            }

                            //还原为初始状态
//                            if (flake.y < -getHeight() || flake.alpha == 0) {
                            if (flake.y < -getHeight()) {
                                flake.y = 0;
                                flake.x = 0;
                                flake.alpha = 255;
                                flake.scale = 0;
                                flake.rotation = (int) (30 * Math.random()) - 15;
                            }
                        }

                    }


                }

                //点击状态下的动画
                for (int i = 0; i < flakesClick.size(); ++i) {
                    Flake flake = flakesClick.get(i);
                    if (flake.isRealeyToShow) {
                        //大小
                        flake.scale = flake.scale + 0.1f;
                        if (flake.scale > 1) {
                            flake.scale = 1;
                        }

                        if (flake.scale == 1) {
                            //位置
                            flake.y += (flake.speedY * secs);
                            flake.x += (flake.speedX*1.5 * secs);

                            //飘动一段时间后改变透明度
                            if (flake.y < -getHeight() / 8) {
                                flake.alpha = flake.alpha - 5;
                                if (flake.alpha < 0) {
                                    flake.alpha = 0;
                                }
                            }

                            //还原为初始状态
                            if (flake.y < -getHeight() || flake.alpha == 0) {
                                flake.y = 0;
                                flake.x = 0;
                                flake.alpha = 255;
                                flake.scale = 0;
                                flake.rotation = (int) (30 * Math.random()) - 15;

                                flake.isRealeyToShow = false;
                            }
                        }

                    }
                }

                // Force a redraw to see the flakes in their new positions and
                // orientations
                invalidate();
            }
        });
        animator.setRepeatCount(ValueAnimator.INFINITE);
        animator.setDuration(3000);

        Message msgX = new Message();
        msgX.what = MSG_X;
        mHandler.sendMessageDelayed(msgX, 500);
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        flakes.clear();
        mListHandler.removeMessages(MSG_LIST);
        setFlakes(LEVEL_BITMAP_NUM + this.level * 2);
        // Cancel animator in case it was already running
        animator.cancel();
        // Set up fps tracking and start the animation
        startTime = System.currentTimeMillis();
        prevTime = startTime;
        animator.start();
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        //正常状态下的动画
        for (int i = 0; i < flakes.size(); ++i) {
            Flake flake = flakes.get(i);
            drawAnim(canvas,flake);
        }
        //点击状态下的动画
        for (int i = 0; i < flakesClick.size(); ++i) {
            Flake flake = flakesClick.get(i);
            drawAnim(canvas,flake);
        }
    }

    /**
     *绘制动画效果
     * @param canvas
     */
    private void drawAnim(Canvas canvas,Flake flake){
        if (flake.isRealeyToShow) {
            //动画效果控制
            if (flake.scale < 1) {//先放大

                int width = (int) (flake.width * flake.scale);
                int height = (int) (flake.height * flake.scale);

                if (width <= 10 || height <= 10) {
                    width = 10;
                    height = 10;
                }
                m.setTranslate(-flake.width / 2, -flake.height / 2);
//                    m.setRotate(flake.rotation);
//                    m.setRotate(flake.rotation,);
//                    m.postRotate(flake.rotation);
                m.postTranslate(mStartX - width / 2 + flake.width / 2, mStartY -height+flake.height/2);
                Bitmap bitmap = Bitmap.createScaledBitmap(flake.bitmap, width
                        , height, true);
                canvas.drawBitmap(bitmap, m, null);
            } else {//再位移
                m.setTranslate(-flake.width / 2, -flake.height / 2);
//                    m.setRotate(flake.rotation);
//                    m.postRotate(flake.rotation);
                m.postTranslate(mStartX + flake.x, mStartY + flake.y-flake.height/2);

                Paint alPaint = new Paint();
                alPaint.setAlpha(flake.alpha);

                canvas.drawBitmap(flake.bitmap, m, alPaint);
            }

        }
    }

    public void pause() {
//        animator.cancel();
    }

    public void resume() {
//        animator.start();
    }

    public void start() {
        animator.cancel();
        animator.start();
    }

    /**
     * 设置动画频率等级，分为1~5等
     *
     * @param level 等级数，例如：1
     */
    public void setLevel(int level) {
        if (level > MAX_LEVEL_NUM) {
            level = MAX_LEVEL_NUM;
        }
        if (level < MIN_LEVEL_NUM) {
            level = MIN_LEVEL_NUM;
        }
        this.level = level;

        setFlakes(LEVEL_BITMAP_NUM + this.level * 2);
    }

    public int getLevel(){
        return level;
    }

    /**
     * Set the specified number of droidflakes.
     */
    private void setFlakes(int quantity) {

        int addNum;
        if(flakes.size() > quantity){
            for (int j = quantity;j < flakes.size();j++){
                flakes.remove(j);
            }
        }else if(flakes.size() < quantity){
            addNum = quantity - flakes.size();
            for (int i = 0; i < addNum; ++i) {
                flakes.add(Flake.createFlake(droids[i % BITMAP_NUM]));
            }

        }

        if(flakesClick.size()<3){
            for (int i = 0; i < 3; ++i) {
                flakesClick.add(Flake.createFlake(droids[i % BITMAP_NUM]));
            }
        }

        //至少显示一个
        flakes.get(0).isRealeyToShow = true;

        Message msgL = new Message();
        msgL.what = MSG_LIST;
        msgL.arg1 = 1;
        mListHandler.sendMessageDelayed(msgL, 800 - 50 * this.level);
    }

    /**
     * 增加点击的礼物动画
     */
    private void addClickFlacks(){
        int num = 0;
        for(int i=0;i<flakesClick.size() && num<3;i++){
            Flake flake = flakesClick.get(i);
            if(!flake.isRealeyToShow){
                num++;
            }
            flake.isRealeyToShow = true;
        }

        if(num<3){
            for(int i=0;i<3-num;i++){
                Flake flake = Flake.createFlake(droids[i%BITMAP_NUM]);
                flake.isRealeyToShow = true;
                flakesClick.add(flake);
            }
        }
    }

    public void onClick(){
        addClickFlacks();
    }

    public void onDestory(){
        if(mHandler != null)
        {
            mHandler.removeCallbacksAndMessages(null);
        }
        if(mListHandler != null)
        {
            mListHandler.removeCallbacksAndMessages(null);
        }
        if(animator != null){
            animator.removeAllUpdateListeners();
        }
        flakes.clear();
        flakesClick.clear();
    }
}
